﻿using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Navigation;
using System.Windows.Threading;
using Windows.UI.Core;

namespace Windows8Accelerator.Core.Xaml.Helpers
{
    public class AppHelper : AppHelperBase
    {
        #region Dispatcher
        public static async Task RunOnUIAsync(Action action, CoreDispatcherPriority priority = CoreDispatcherPriority.Low)
        {
            try
            { 
                action();
                return;
            }
            catch{}
            //if (Dispatcher.HasThreadAccess)
            //    action();
            //else
            //    await Dispatcher.RunAsync(priority, () => action());
            Dispatcher.BeginInvoke(action);
        }

        private static Dispatcher _Dispatcher;
        public static Dispatcher Dispatcher
        {
            get
            {
                return _Dispatcher;
            }
        }

        public override void RunOnUIAsync(Action action)
        {
            RunOnUIAsync(action);
        }
        #endregion Dispatcher

        public static async Task NavigateToUriAsync(Uri uri, object parameter)
        {
            var appHelper = AppHelperBase.Instance as AppHelper;
            appHelper.NavigationParameter = parameter;
            AppHelper.CurrentPage.NavigationService.Navigate(uri);
        }

        #region Abstract Methods Implementation

        private object NavigationParameter;

        public override async Task NavigateAsync(Type pageType)
        {
            NavigationParameter = null;
            CurrentPage.NavigationService.Navigate(TypeToUri(pageType));
        }

        public override async Task NavigateAsync(Type pageType, object parameter)
        {
            NavigationParameter = parameter;
            CurrentPage.NavigationService.Navigate(TypeToUri(pageType));
        }

        public override ApplicationViewMode ApplicationViewMode
        {
            get 
            {
                if (CurrentPage == null)
                    return ApplicationViewMode.Snapped;
                switch (CurrentPage.Orientation)
                {
                    case PageOrientation.Landscape:
                    case PageOrientation.LandscapeLeft:
                    case PageOrientation.LandscapeRight:
                    case PageOrientation.None:
                    default:
                        return ApplicationViewMode.Landscape;
                    case PageOrientation.Portrait:
                    case PageOrientation.PortraitDown:
                    case PageOrientation.PortraitUp:
                        return ApplicationViewMode.Snapped;
                }
            }
        }

        public override void TryUnsnap()
        {
        }
     
        protected override void InternalInitialize()
        {
            Application.Current.UnhandledException += Current_UnhandledException;

            // Phone-specific initialization
            InitializePhoneApplication();
            // Language display initialization
            InitializeLanguage();
            // Show graphics profiling information while debugging.
            if (Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                Application.Current.Host.Settings.EnableFrameRateCounter = true;

                // Show the areas of the app that are being redrawn in each frame.
                //Application.Current.Host.Settings.EnableRedrawRegions = true;

                // Enable non-production analysis visualization mode,
                // which shows areas of a page that are handed off to GPU with a colored overlay.
                //Application.Current.Host.Settings.EnableCacheVisualization = true;

                // Prevent the screen from turning off while under the debugger by disabling
                // the application's idle detection.
                // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
                // and consume battery power when the user is not using the phone.
                PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
            }
        }

        public override async Task NavigateBack()
        {
            if (CanNavigateBack)
                Frame.GoBack();
        }

        public override bool CanNavigateBack
        {
            get 
            {
                if (Frame == null)
                    return false;
                return Frame.CanGoBack; 
            }
        }

        #endregion

        #region Platform Specific Code

        public static PhoneApplicationFrame Frame { get; private set; }

        public static PhoneApplicationPage CurrentPage
        {
            get
            {
                if (Frame == null)
                    return null;
                return Frame.Content as PhoneApplicationPage;
            }
        }

        void Current_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (Debugger.IsAttached && !(e.ExceptionObject is System.Windows.LayoutCycleException))
            {
                Debugger.Break();
            }
            e.Handled = true;
        }

        private bool phoneApplicationInitialized = false;

        private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;
            Frame = new PhoneApplicationFrame();
            Frame.Navigated += CompleteInitializePhoneApplication;
            Frame.Navigated += Frame_Navigated;
            Frame.NavigationFailed += RootFrame_NavigationFailed;
            Frame.Navigated += CheckForResetNavigation;
            phoneApplicationInitialized = true;
        }

        void Frame_Navigated(object sender, NavigationEventArgs e)
        {
            base.Frame_Navigated(e.NavigationMode.ToString(), e.Content, NavigationParameter);
        }

        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            if (Application.Current.RootVisual != Frame)
                Application.Current.RootVisual = Frame;
            _Dispatcher = Application.Current.RootVisual.Dispatcher;
            Frame.Navigated -= CompleteInitializePhoneApplication;
        }

        private void CheckForResetNavigation(object sender, NavigationEventArgs e)
        {
            if (e.NavigationMode == NavigationMode.Reset)
                Frame.Navigated += ClearBackStackAfterReset;
        }

        private void ClearBackStackAfterReset(object sender, NavigationEventArgs e)
        {
            Frame.Navigated -= ClearBackStackAfterReset;
            if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
                return;
            while (Frame.RemoveBackEntry() != null) ;
        }

        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (Debugger.IsAttached)
            {
                Debugger.Break();
            }
        }

        private void InitializeLanguage()
        {
            try
            {
                Frame.Language = XmlLanguage.GetLanguage(ResourceHelper.DefaultLanguage);
                FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), ResourceHelper.DefaultFlowDirection);
                Frame.FlowDirection = flow;
            }
            catch
            {
                if (Debugger.IsAttached)
                {
                    Debugger.Break();
                }
                throw;
            }
        }

        private static void ClearBackEntries(PhoneApplicationPage page)
        {
            while (page.NavigationService.BackStack != null & page.NavigationService.BackStack.Count() > 0)
                page.NavigationService.RemoveBackEntry();
        }

        public static void AddConfirmationOnExit(PhoneApplicationPage page, string title, string message)
        {
            page.BackKeyPress += (sender, e) => {
                if (MessageBox.Show(message, title, MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                    ClearBackEntries(page);
                else
                    e.Cancel = true;
            };
        }

        #endregion

        public override async Task ShowErrorMessageAndQuitAsync(string title, string message)
        {
            MessageBox.Show(message, title, MessageBoxButton.OK);
            Application.Current.Terminate();
        }

        public override async Task ShowErrorMessageAndGoBackAsync(string title, string message)
        {
            MessageBox.Show(message, title, MessageBoxButton.OK);
            await NavigateBack();
        }
    }
}
